#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XShm.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syscall.h>
#include <linux/memfd.h>

#define WIDTH  400
#define HEIGHT 300

int main() {
    Display *display;
    Window window;
    GC gc;
    XEvent event;
    int screen;
    XImage *image;
    XShmSegmentInfo shminfo;

    // 1. 连接到 X Server
    display = XOpenDisplay(NULL);
    if (!display) {
        fprintf(stderr, "无法打开 X 显示\n");
        return 1;
    }
    screen = DefaultScreen(display);

    // 2. 创建窗口
    window = XCreateSimpleWindow(display, RootWindow(display, screen),
                                0, 0, WIDTH, HEIGHT, 1,
                                BlackPixel(display, screen),
                                WhitePixel(display, screen));
    XStoreName(display, window, "X11 + memfd_create 共享内存演示");
    XSelectInput(display, window, ExposureMask | KeyPressMask);
    XMapWindow(display, window);

    // 3. 使用 memfd_create 创建匿名共享内存
    int fd = syscall(__NR_memfd_create, "buffer", MFD_ALLOW_SEALING);
    //int fd = memfd_create("x11-shm", 0);
    if (fd == -1) {
        perror("memfd_create 失败");
        XCloseDisplay(display);
        return 1;
    }

    // 4. 调整共享内存大小（容纳图像数据）
    size_t image_size = WIDTH * HEIGHT * 4; // 32位 ARGB
    if (ftruncate(fd, image_size)) {
        perror("ftruncate 失败");
        close(fd);
        XCloseDisplay(display);
        return 1;
    }

    // 5. 映射共享内存
    unsigned char *data = mmap(NULL, image_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (data == MAP_FAILED) {
        perror("mmap 失败");
        close(fd);
        XCloseDisplay(display);
        return 1;
    }

    // 6. 初始化 MIT-SHM 扩展
    if (!XShmQueryExtension(display)) {
        fprintf(stderr, "X Server 不支持 MIT-SHM 扩展\n");
        munmap(data, image_size);
        close(fd);
        XCloseDisplay(display);
        return 1;
    }

    // 7. 创建 XImage 并关联共享内存
    image = XShmCreateImage(display, DefaultVisual(display, screen),
                           24, ZPixmap, NULL, &shminfo, WIDTH, HEIGHT);

    shminfo.shmid = fd; // 关键：传递 memfd 文件描述符
    shminfo.shmaddr = data;
    shminfo.readOnly = False;

    if (!XShmAttach(display, &shminfo)) {
        fprintf(stderr, "XShmAttach 失败\n");
        XDestroyImage(image);
        munmap(data, image_size);
        close(fd);
        XCloseDisplay(display);
        return 1;
    }

    // 8. 主循环：动态更新共享内存并显示
    gc = XCreateGC(display, window, 0, NULL);
    int x = 0, y = 0, dx = 2, dy = 2;

    while (1) {
        if (XPending(display)) {
            XNextEvent(display, &event);
            if (event.type == KeyPress)
                break;
        }

        // 更新动画位置
        x += dx; y += dy;
        if (x <= 0 || x >= WIDTH - 50) dx = -dx;
        if (y <= 0 || y >= HEIGHT - 50) dy = -dy;

        // 在共享内存中绘制（直接操作 data）
        memset(data, 0xFF, image_size); // 白色背景
        for (int py = y; py < y + 50; py++) {
            for (int px = x; px < x + 50; px++) {
                int pos = (py * WIDTH + px) * 4;
                data[pos] = 0x00;     // B
                data[pos + 1] = 0x00; // G
                data[pos + 2] = 0xFF; // R
                data[pos + 3] = 0xFF; // A
            }
        }

        // 提交到窗口
        XShmPutImage(display, window, gc, image,
                     0, 0, 0, 0, WIDTH, HEIGHT, False);
        XFlush(display);
        usleep(10000); // 10ms 延迟
    }

    // 9. 清理资源
    XShmDetach(display, &shminfo);
    XDestroyImage(image);
    munmap(data, image_size);
    close(fd);
    XFreeGC(display, gc);
    XDestroyWindow(display, window);
    XCloseDisplay(display);
    return 0;
}
